package com.bsdk.install.device.lockLora.v1.cmd;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.bsdk.install.device.constants.LockConstants;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;

@Slf4j
public class ANALYSIS extends LockConstants {

    private JSONObject reData = new JSONObject();


    /***
     * @description
     * @author
     * @throws
     * @return com.alibaba.fastjson2.JSONObject
     * @time 16:51
     */
    public JSONObject dealJsonData(JSONObject jsonObject) {

        int i, j = 0, k;
        String str_data;
        String tmp;
        int len;
        byte[] hex_data = new byte[200];

        if(jsonObject == null){

            reData.put("code", STATUS_ERROR);
            return reData;
        }
        str_data = (String) jsonObject.get("data");
        len = str_data.length();
        if (len == 0) {
            reData.put("code", STATUS_ERROR);
            return reData;
        }
        log.info("str_data：" + str_data);
        len = len / 2;
        //写一个转换函数
        for (i = 0; i < len; i++) {
            k = 2 * i;
            tmp = str_data.substring(k, (k + 2));
            k = Integer.parseInt(tmp, 16);
            hex_data[j++] = (byte) k;

        }
        log.info("16:", Arrays.toString(hex_data));
        log.info("str_data：" + str_data);
        JSONObject retJsonObject;
        //先检测模块的协议
        retJsonObject = Moudle_Packet_analysis(hex_data, j);
        if(retJsonObject.isEmpty()==false)return retJsonObject;
        return Packet_analysis(hex_data, j);

    }



    public JSONObject Packet_analysis(byte[] m_data, int len) {
        JSONObject jsonObject = new JSONObject();
        int m_rev_state = CMD_RECEIVE_HEAD;
        int data_total_len = 0;
        int rcv_len = 0;
        byte rcv_char;
        byte[] m_packet_data = new byte[100];
        int j = 0, i;
        if (len < 1) return jsonObject;

        while (len != j) {
            rcv_char = m_data[j++];
            switch (m_rev_state) {
                case CMD_RECEIVE_HEAD:
                    if (rcv_char == 0x02) m_rev_state = CMD_RECEIVE_LEN;
                    rcv_len = 0;
                    m_packet_data[rcv_len++] = rcv_char;
                    break;
                case CMD_RECEIVE_LEN://命令包+包类型
                    m_packet_data[rcv_len++] = rcv_char;
                    data_total_len = rcv_char + 2;
                    m_rev_state = CMD_RECEIVE_CMD_DATA;
                    break;
                case CMD_RECEIVE_CMD_DATA:
                    m_packet_data[rcv_len++] = rcv_char;
                    if (rcv_len == data_total_len) m_rev_state = CMD_RECEIVE_TAIL;
                    break;
                case CMD_RECEIVE_TAIL:
                    if (rcv_char == 0x03) {
                        m_packet_data[rcv_len++] = rcv_char;
                        m_rev_state = CMD_RECEIVE_CRC;
                    } else {
                        m_rev_state = CMD_RECEIVE_HEAD;
                    }
                    break;
                case CMD_RECEIVE_CRC: //异或
                    if (rcv_char == rev_check_xor(m_packet_data, rcv_len)) {
                        m_rev_state = CMD_RECEIVE_OK;
                        m_packet_data[rcv_len++] = rcv_char;

                    } else
                        m_rev_state = CMD_RECEIVE_HEAD;
                    break;
                default:
                    break;
            }
            if (CMD_RECEIVE_OK == m_rev_state) {
                jsonObject = packet_process(m_packet_data, rcv_len);
                m_rev_state = CMD_RECEIVE_HEAD;
            }
        }
        return jsonObject;
    }


    public JSONObject packet_process(byte[] buf, int len) {
        JSONObject jsonObject = new JSONObject();
        int i;
        byte m_packet;
        byte m_CMD;
        //byte m_buf[20];

        //len = buf[1];
        m_packet = buf[2];
        m_CMD = buf[3];
        switch (m_packet) {
            case TYPE_LOCK_SERVER_NORESPONE:
                jsonObject = CMD_noRespone(buf, len);
                break;
            case PACKET_TYPE_LOCK_RESP:
                jsonObject = CMD_Respone(buf, len);
                break;
            default:
                break;

        }
        return jsonObject;

    }

    public JSONObject CMD_noRespone(byte[] buf, int len) {

        int i,j;
        int pw_len;
        StringBuilder tmp = new StringBuilder();
        JSONObject jsonData = new JSONObject();
        Cmd cmd =new Cmd();
        switch (buf[3]) {
            case CMD_RING_REPORT:
                log.info("ring!!!");
                reData.put("code",BELL_SOUND);
                reData.put("time",cmd.buildTimeString(buf,4));
                break;
            case CMD_REQEST_UNLOCK_REPORT://本地请求远程开锁
                reData.put("code",REQEST_UNLOCK_REPORT);
                break;
            case CMD_UNLOCK_RECORD_REPORT:
                log.info("unlock!!!");
                reData.put("code",LOCK_OPEN);
                jsonData.put("type",buf[4]);//01H：密码用户、02H：卡用户、03H：指纹用户
                jsonData.put("number",(buf[5]*0x100)+buf[6]);
                j = 7;
                pw_len = buf[j++];
                for(i = 0;i<7;i++)
                {
                    tmp.append(String.format("%02x",buf[j++]));
                }
                jsonData.put("value",tmp.toString().substring(0,pw_len));
                jsonData.put("battery",buf[j++]);
                jsonData.put("time",cmd.buildTimeString(buf,j));
                reData.put("data",jsonData);
                break;
            case CMD_ADD_PW_USER_REPORT:// 添加密码用户上报
                reData.put("code",ADD_PW_USER_REPORT);
                jsonData.put("type",buf[4]);//01H：普通用户、02H：管理用户、03H：劫持用户
                jsonData.put("number",(buf[5]*0x100)+buf[6]);//用户编号
                j = 7;
                for(i = 0;i<7;i++)
                {
                    if(buf[j] == 0xFF)break;
                    tmp.append(String.format("%02x",buf[j++]));
                }
                jsonData.put("value",tmp.toString().replace("f",""));//卡号或密码号
                jsonData.put("time",cmd.buildTimeString(buf,j));//上报时间
                reData.put("data",jsonData);

                break;
            case CMD_ADD_CARD_USER_REPORT:// 添加卡片用户上报
                reData.put("code",ADD_CARD_USER_REPORT);
                jsonData.put("type",buf[4]);//01H：普通用户、02H：管理用户、03H：劫持用户
                jsonData.put("number",(buf[5]*0x100)+buf[6]);//用户编号
                j = 7;
                for(i = 0;i<7;i++)
                {
                    if(buf[j] == 0x00)break;
                    tmp.append(String.format("%02x",buf[j++]));
                }
                jsonData.put("value",tmp.toString());//卡号
                jsonData.put("time",cmd.buildTimeString(buf,j));//上报时间
                reData.put("data",jsonData);
                break;
            case CMD_ADD_FP_USER_REPORT:// 添加指纹用户上报
                reData.put("code",ADD_FP_USER_REPORT);
                jsonData.put("type",buf[4]);//01H：普通用户、02H：管理用户、03H：劫持用户
                jsonData.put("number",(buf[5]*0x100)+buf[6]);//用户编号
                j = 7;
                for(i = 0;i<7;i++)
                {
                    if(buf[j] == 0xFF)break;
                    tmp.append(String.format("%02x",buf[j++]));
                }
                jsonData.put("value",tmp.toString());//指纹ID
                jsonData.put("time",cmd.buildTimeString(buf,j));//上报时间
                reData.put("data",jsonData);
                break;
            case CMD_DEL_PW_USER_REPORT:// 删除密码用户上报
                reData.put("code",DEL_PW_USER_REPORT);
                jsonData.put("number",(buf[4]*0x100)+buf[5]);//用户编号
                j = 6;
                jsonData.put("time",cmd.buildTimeString(buf,j));//上报时间
                reData.put("data",jsonData);
                break;
            case CMD_DEL_CARD_USER_REPORT:// 删除卡用户上报
                reData.put("code",DEL_CARD_USER_REPORT);
                jsonData.put("number",(buf[5]*0x100)+buf[6]);//用户编号
                j = 7;
                jsonData.put("time",cmd.buildTimeString(buf,j));//上报时间
                reData.put("data",jsonData);
                break;
            case CMD_DEL_FP_USER_REPORT:// 删除指纹用户上报
                reData.put("code",DEL_FP_USER_REPORT);
                jsonData.put("number",(buf[5]*0x100)+buf[6]);//用户编号
                j = 7;
                jsonData.put("time",cmd.buildTimeString(buf,j));//上报时间
                reData.put("data",jsonData);
                break;
            case CMD_VERIFY_PW_REPORT://密码多次验证失败上报
                reData.put("code",VERIFY_PW_REPORT);
                reData.put("time",cmd.buildTimeString(buf,4));
                break;
            case CMD_VERIFY_CARD_REPORT://卡多次验证失败上报
                reData.put("code",VERIFY_CARD_REPORT);
                reData.put("time",cmd.buildTimeString(buf,4));
                break;
            case CMD_VERIFY_FP_REPORT:// 指纹多次验证失败上报
                reData.put("code",VERIFY_FP_REPORT);
                reData.put("time",cmd.buildTimeString(buf,4));
                break;
            case CMD_ANTI_ALARM_REPORT: //防撬报警
                reData.put("code", ANTI_ALARM_REPORT);
                reData.put("time",cmd.buildTimeString(buf,4));
                break;
            case CMD_LOWBAT_ALARM_REPORT: //低电报警
                reData.put("code", LOWBAT_ALARM_REPORT);
                reData.put("time",cmd.buildTimeString(buf,4));
                break;
            case CMD_ABDCT_ALRM_REPORT: //劫持报警
                reData.put("code", ABDCT_ALRM_REPORT);
                reData.put("time",cmd.buildTimeString(buf,4));
                break;
            case CMD_SYS_LOCKED_REPORT://多次输入，系统锁定
                reData.put("code", SYS_LOCKED_REPORT);
                reData.put("time",cmd.buildTimeString(buf,4));
                break;
            case CMD_KEY_REMOTE_RESET_REPORT: //复位上报要特殊处理
                reData.put("code", KEY_REMOTE_RESET_REPORT);
                reData.put("time",cmd.buildTimeString(buf,4));
                break;

            default:
                break;
        }
        return reData;
    }

    public JSONObject CMD_Respone(byte[] buf, int len) {
        int i,j,int_tmp;
        int userId;
        StringBuilder tmp = new StringBuilder();
        String pw;
        StringBuilder rcv_data = new StringBuilder();
        int Isfrozen = 0;
        for(i = 0;i< len;i++) {
            rcv_data.append(String.format("%02X", buf[i]));
        }
        JSONObject jsonData = new JSONObject();
        reData.put("code", STATUS_SUCCESS);
        switch (buf[3]) {
            case CMD_REMOTE_UNLOCK_REQ://远程开锁
                //0202863003b5
                //reData.put("code", REMOTE_UNLOCK_REPORT);
                reData.put("code", STATUS_SUCCESS);
                //reData.put("data","");
                break;
            case CMD_ADJUST_TIME_REQ://下发校准时间  0x3A
                //0208863A18011E0F1E230380
                //"2024-01-22 12:12:12"
                int_tmp = 2000 + buf[4];
                tmp.append(String.format("%04d", int_tmp));//年
                tmp.append("-");
                int_tmp = buf[5];
                tmp.append(String.format("%02d", int_tmp));//月
                tmp.append("-");
                int_tmp = buf[6];
                tmp.append(String.format("%02d", int_tmp));//日
                tmp.append(" ");
                int_tmp = buf[7];
                tmp.append(String.format("%02d", int_tmp));//时
                tmp.append(":");
                int_tmp = buf[8];
                tmp.append(String.format("%02d", int_tmp));//分
                tmp.append(":");
                int_tmp = buf[9];
                tmp.append(String.format("%02d", int_tmp));//秒
                pw = tmp.toString(); //pw 时间，临时借用
                jsonData.put("time", pw);
                break;
            case CMD_ADDPASS_BY_ID_REQ: //添加修改密码用户 0X3E
                //020E863E0100020004666666FFFFFFFF03D6
                reData.put("code", STATUS_SUCCESS);
                if (buf[4] > 0x03) {
                    //错误代码
                    if (buf[4] == 0x41) jsonData.put("error",USER_EXIST);
                    if (buf[4] == 0x42) jsonData.put("error", USER_TYPE_ERROR);
                    if (buf[4] == 0x43) jsonData.put("error", USER_ID_EXCEED);
                    if (buf[4] == 0x44) jsonData.put("error", PASSWORD_EXCEED);
                    if (buf[4] == 0x45) jsonData.put("error", USER_ADD_FAIL);
                    //错误返回
                    break;
                }
                else
                {
                    //buf[4]用户类型
                    if (buf[4] == 0x00) jsonData.put("userType", USER_TYPE_NORMAL);
                    if (buf[4] == 0x01) jsonData.put("userType", USER_TYPE_ADMIN);
                    if (buf[4] == 0x02) jsonData.put("userType", USER_TYPE_COERCE);
                }

                userId = (buf[5] * 0x100) + buf[6];//buf[5]、buf[6]用户编号

                //buf[7]、buf[8]硬件ID
                j = 9;
                for (i = 0; i < 7; i++) {
                    if (buf[j] == (byte)0xFF) break;
                    tmp.append(String.format("%02X", buf[j]));
                    j++;
                }
                //buf[9]、buf[10]、buf[11]、buf[12]、buf[13]、buf[14]、buf[15]密码
                //循环方式
  /*              {

                    if(buf[16] == 0x01)jsonData.put("cycleType",USER_CYCLE_TYPE_DAY);
                    else if(buf[16] == 0x02)jsonData.put("cycleType",USER_CYCLE_TYPE_WEEK);
                    else if(buf[16] == 0x03)jsonData.put("cycleType",USER_CYCLE_TYPE_MONTH);
                    else jsonData.put("cycleType",USER_CYCLE_TYPE_NONE);
                }
*/
                //
                //半个字节F没有处理，回头调测一下
                pw = tmp.toString();
                //log.info("userId = %d,password = %s",userId,pw);
                jsonData.put("userId",userId);
                jsonData.put("password", pw);



                //log.info("CMD_ADDPASS_BY_ID_REQ");
                break;


            case CMD_DIS_ENABLE_BY_ID_REQ://通过用户编号冻结、解冻用户 0x3c
                if (buf[4] > 0x03) {
                    if (buf[4] == 0x40) reData.put("code",USER_NOT_EXIST);
                    if (buf[4] == 0x4A) reData.put("code",CIRCLE_MODE_ERROR);
                    break;
                }
                Isfrozen = buf[4]; //0 解冻 1 冻结
                userId = (buf[5] * 0x100) + buf[6];//buf[5]、buf[6]用户编号
                jsonData.put("userId", userId);
                if(Isfrozen>0) jsonData.put("frozen", USER_FROZEN_STATUS);
                else jsonData.put("frozen", USER_UNFROZEN_STATUS);

                //log.info("userId = %d,Isfrozen = %d",userId,Isfrozen);
                //log.info("CMD_DIS_ENABLE_BY_ID_REQ");
                break;
            case CMD_DELPASS_BY_ID_REQ://通过ID删除用户　　0x38
                //buf[4]用户类型
                /*if (buf[4] > 0x03) {
                    if (buf[4] == 0x40) reData.put("code",USER_NOT_EXIST);
                    if (buf[4] == 0x48) reData.put("code",USER_DELETE_FAIL);
                    break;
                }
                else
                {
                    userId = (buf[4] * 0x100) + buf[5];//buf[5]、buf[6]用户编号
                    jsonData.put("userId",userId);
                }
                break;*/
            case CMD_MODIVALID_BY_ID_REQ://通过ID修改有效期　　0x41
                //buf[4]用户类型
                if (buf[4] > 0x03) {
                    if (buf[4] == 0x40) reData.put("code",USER_NOT_EXIST);
                    if (buf[4] == 0x42) reData.put("code",USER_TYPE_ERROR);
                    if (buf[4] == 0x44) reData.put("code",PASSWORD_EXCEED);
                    break;
                }
                else
                {
                    //buf[4]用户类型
                    if (buf[4] == 0x00) jsonData.put("userType", USER_TYPE_NORMAL);
                    if (buf[4] == 0x01) jsonData.put("userType", USER_TYPE_ADMIN);
                    if (buf[4] == 0x02) jsonData.put("userType", USER_TYPE_COERCE);
                }
                userId = (buf[5] * 0x100) + buf[6];//buf[5]、buf[6]用户编号
                jsonData.put("userId",userId);

                break;
            case CMD_MODIPASS_BY_ID_REQ://通过ID修改密码    0x42
                if (buf[4] > 0x03) {
                    if (buf[4] == 0x40) reData.put("code",USER_NOT_EXIST);
                    if (buf[4] == 0x42) reData.put("code",USER_TYPE_ERROR);
                    if (buf[4] == 0x44) reData.put("code",PASSWORD_EXCEED);
                    break;
                }
                else
                {
                    //buf[4]用户类型
                    if (buf[4] == 0x00) jsonData.put("userType", USER_TYPE_NORMAL);
                    if (buf[4] == 0x01) jsonData.put("userType", USER_TYPE_ADMIN);
                    if (buf[4] == 0x02) jsonData.put("userType", USER_TYPE_COERCE);
                }
                //buf[4]用户类型
                userId = (buf[5] * 0x100) + buf[6];//buf[5]、buf[6]用户编号
                jsonData.put("userId",userId);
                break;
            case CMD_ADD_ADMIN_PASSWORD_REQ:
                //020B863D000012345678FFFFFF0346
                userId = (buf[4] * 0x100) + buf[5];//buf[5]、buf[6]用户编号
                j = 6;
                for (i = 0; i < 7; i++) {
                    if (buf[j] == (byte)0xFF) break;
                    tmp.append(String.format("%02X", buf[j]));
                    j++;
                }
                pw = tmp.toString();
                //log.info("userId = %d,password = %s",userId,pw);
                jsonData.put("userId",userId);
                jsonData.put("password", pw);
                break;
            default:

                break;


        }
        reData.put("data", jsonData);
        //reData.put("Raw_data",rcv_data);
        log.info(JSON.toJSONString(reData));
        return reData;
    }

    protected final byte rev_check_xor(byte[] m_data, int len) {
        byte xor = 0;
        int i;
        for (i = 0; i < len; i++) {
            xor ^= m_data[i];
        }
        return xor;

    }

    public JSONObject Moudle_Packet_analysis(byte[] m_data, int len) {
        JSONObject jsonObject = new JSONObject();
        int m_rev_state = MOUDLE_CMD_RECEIVE_HEAD;
        int data_total_len = 0;
        int rcv_len = 0;
        byte rcv_char;
        byte[] m_packet_data = new byte[100];
        int j = 0, i;
        if (len < 1) return jsonObject;

        while (len != j) {
            rcv_char = m_data[j++];
            switch (m_rev_state) {
                case MOUDLE_CMD_RECEIVE_HEAD:
                    if (rcv_char == 0x02) m_rev_state = MOUDLE_CMD_RECEIVE_LEN1;
                    rcv_len = 0;
                    m_packet_data[rcv_len++] = rcv_char;
                    break;
                case MOUDLE_CMD_RECEIVE_LEN1://
                    m_packet_data[rcv_len++] = rcv_char;
                    data_total_len = rcv_char;
                    m_rev_state = MOUDLE_CMD_RECEIVE_LEN2;
                    break;
                case MOUDLE_CMD_RECEIVE_LEN2://
                    m_packet_data[rcv_len++] = rcv_char;
                    data_total_len = (rcv_char*0x100) + data_total_len + 3;
                    m_rev_state = MOUDLE_CMD_RECEIVE_CMD_DATA;
                    break;
                case MOUDLE_CMD_RECEIVE_CMD_DATA:
                    m_packet_data[rcv_len++] = rcv_char;
                    if (rcv_len == data_total_len) m_rev_state = MOUDLE_CMD_RECEIVE_CRC;
                    break;
                case MOUDLE_CMD_RECEIVE_CRC: //异或
                    if (rcv_char == crc_8n(m_packet_data, rcv_len)) {
                        m_rev_state = MOUDLE_CMD_RECEIVE_TAIL;
                        m_packet_data[rcv_len++] = rcv_char;

                    } else{
                        m_packet_data[rcv_len++] = rcv_char;
                        m_rev_state = MOUDLE_CMD_RECEIVE_TAIL;
                    }

                    break;
                case MOUDLE_CMD_RECEIVE_TAIL:
                    if (rcv_char == (byte)0x0FF) {
                        m_packet_data[rcv_len++] = rcv_char;
                        m_rev_state = MOUDLE_CMD_RECEIVE_OK;
                    } else {
                        m_rev_state = MOUDLE_CMD_RECEIVE_HEAD;
                    }
                    break;

                default:
                    break;
            }
            if (MOUDLE_CMD_RECEIVE_OK == m_rev_state) {
                jsonObject = moudl_packet_process(m_packet_data, rcv_len);
                m_rev_state = MOUDLE_CMD_RECEIVE_HEAD;
            }
        }
        return jsonObject;
    }
    public JSONObject moudl_packet_process(byte[] buf, int len) {
        JSONObject jsonObject = new JSONObject();
        int i,j;
        byte m_packet;
        byte m_CMD;
        StringBuilder rcv_data = new StringBuilder();
            for(i = 0;i< len;i++) {
            rcv_data.append(String.format("%02X", buf[i]));
        }
        JSONObject jsonData = new JSONObject();
        StringBuilder tmp_data = new StringBuilder();
        //02010077ECFF
        reData.put("code", STATUS_SUCCESS);
        m_CMD = buf[3];
        switch (m_CMD) {
            case MOUDLE_CMD_REGIST_RESP:
                jsonObject.put("gwChn",buf[4]);
                //jsonObject = CMD_noRespone(buf, len);
                break;
            case MOUDLE_CMD_PING_RESP:
                //buf[4] 保留
                j = 5;
                jsonObject.put("gwChn",buf[j++]);
                for(i = 0;i < 4;i++)tmp_data.append(String.format("%02X", buf[j++]));
                jsonObject.put("gwMac",tmp_data.toString());
                tmp_data.delete(0, tmp_data.length());
                for(i = 0;i < 5;i++)tmp_data.append(String.format("%c", buf[j++]));
                jsonObject.put("version",tmp_data.toString());
                //jsonObject = CMD_Respone(buf, len);
                break;
            case MOUDLE_CMD_SET_REGIST_RESP://Regist 指令
                j = 6;
                //for(i = 0;i < 4;i++)tmp_data.append(String.format("%02X", buf[j++]));
               // jsonObject.put("gwMac",tmp_data.toString());
                break;
            case MOUDLE_CMD_REQ_PING_RESP://查询Regist
                j = 6;
                for(i = 0;i < 4;i++)tmp_data.append(String.format("%02X", buf[j++]));
                jsonObject.put("gwMac",tmp_data.toString());
            default:
                break;

        }
        reData.put("data",jsonObject);
        //reData.put("Raw_data",rcv_data);
        return reData;

    }


    /**
     *
     * 这个有错误
     * @param ptr
     * @param n
     * @return
     */
    protected final byte crc_8n(byte[] ptr, int n)
    {
        int i = 0;
        byte j=8;
        byte cbit,out;
        byte crc=0x79,crc_a=0,crc_b=0;
         do{
            crc_a = ptr[i++];
            j=8;
            cbit=1;
            do{
                crc_b=crc_a;
                crc_b=(byte)(crc_b^crc);
                out=(byte)(crc_b&cbit);
                //	crc_b=crc_b>>1;
                if(out!=0){
                    crc=(byte)(crc^0X18);
                    crc=(byte)(crc>>1);
                    crc|=0x80;
                }
                else
                    crc=(byte)(crc>>1);
                crc_a=(byte)(crc_a>>1);

            }while((--j)!=0);
        }while((--n)!=0);
        return crc;
    }


}